home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / gnuwget.zip / wget-1.4.3 / src / cmpt.c < prev    next >
C/C++ Source or Header  |  1997-02-08  |  28KB  |  1,087 lines

  1. /* Replacements for routines missing on some systems.
  2.    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18.  
  19. #ifdef HAVE_CONFIG_H
  20. #  include <config.h>
  21. #endif /* HAVE_CONFIG_H */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #ifdef HAVE_STRING_H
  26. #  include <string.h>
  27. #else
  28. #  include <strings.h>
  29. #endif /* HAVE_STRING_H */
  30. #include <ctype.h>
  31.  
  32. #include <sys/types.h>
  33. #ifdef HAVE_UNISTD_H
  34. #  include <unistd.h>
  35. #endif
  36. #include <limits.h>
  37.  
  38. #include "wget.h"
  39. #include "cmpt.h"
  40.  
  41. /* Some systems don't have some str* functions in libc.  Here we
  42.    define them.  The same goes for strptime.  */
  43.  
  44. #ifndef HAVE_STRCASECMP
  45. /* From GNU libc. */
  46. /* Compare S1 and S2, ignoring case, returning less than, equal to or
  47.    greater than zero if S1 is lexiographically less than,
  48.    equal to or greater than S2.  */
  49. int
  50. strcasecmp(const char *s1, const char *s2)
  51. {
  52.    register const unsigned char *p1 = (const unsigned char *) s1;
  53.    register const unsigned char *p2 = (const unsigned char *) s2;
  54.    unsigned char c1, c2;
  55.  
  56.    if (p1 == p2)
  57.       return 0;
  58.  
  59.    do
  60.    {
  61.       c1 = tolower (*p1++);
  62.       c2 = tolower (*p2++);
  63.       if (c1 == '\0')
  64.      break;
  65.    }
  66.    while (c1 == c2);
  67.  
  68.    return c1 - c2;
  69. }
  70. #endif /* HAVE_STRCASECMP */
  71.  
  72. #ifndef HAVE_STRNCASECMP
  73. /* From GNU libc. */
  74. /* Compare no more than N characters of S1 and S2,
  75.    ignoring case, returning less than, equal to or
  76.    greater than zero if S1 is lexicographically less
  77.    than, equal to or greater than S2.  */
  78. int
  79. strncasecmp(const char *s1, const char *s2, size_t n)
  80. {
  81.    register const unsigned char *p1 = (const unsigned char *) s1;
  82.    register const unsigned char *p2 = (const unsigned char *) s2;
  83.    unsigned char c1, c2;
  84.  
  85.    if (p1 == p2 || n == 0)
  86.       return 0;
  87.  
  88.    do
  89.    {
  90.       c1 = tolower (*p1++);
  91.       c2 = tolower (*p2++);
  92.       if (c1 == '\0' || c1 != c2)
  93.      return c1 - c2;
  94.    } while (--n > 0);
  95.  
  96.    return c1 - c2;
  97. }
  98. #endif /* HAVE_STRNCASECMP */
  99.  
  100. #ifndef HAVE_STRSTR
  101. /* From GNU libc. */
  102. /* Return the first ocurrence of NEEDLE in HAYSTACK.  */
  103. char *
  104. strstr(const char *const haystack, const char *const needle)
  105. {
  106.    register const char *const needle_end = strchr(needle, '\0');
  107.    register const char *const haystack_end = strchr(haystack, '\0');
  108.    register const size_t needle_len = needle_end - needle;
  109.    register const size_t needle_last = needle_len - 1;
  110.    register const char *begin;
  111.  
  112.    if (needle_len == 0)
  113.       return (char *) haystack;    /* ANSI 4.11.5.7, line 25.  */
  114.    if ((size_t) (haystack_end - haystack) < needle_len)
  115.       return NULL;
  116.  
  117.    for (begin = &haystack[needle_last]; begin < haystack_end; ++begin)
  118.    {
  119.       register const char *n = &needle[needle_last];
  120.       register const char *h = begin;
  121.  
  122.       do
  123.      if (*h != *n)
  124.         goto loop;        /* continue for loop */
  125.       while (--n >= needle && --h >= haystack);
  126.  
  127.       return (char *) h;
  128.  
  129.      loop:;
  130.    }
  131.  
  132.    return NULL;
  133. }
  134. #endif /* HAVE_STRSTR */
  135.  
  136. #ifndef HAVE_MKTIME
  137. /* From GNU libc 2.0. */
  138.  
  139. /* Assume that leap seconds are possible, unless told otherwise.
  140.    If the host has a `zic' command with a `-L leapsecondfilename' option,
  141.    then it supports leap seconds; otherwise it probably doesn't.  */
  142. #ifndef LEAP_SECONDS_POSSIBLE
  143. #define LEAP_SECONDS_POSSIBLE 1
  144. #endif
  145.  
  146. #ifndef CHAR_BIT
  147. #define CHAR_BIT 8
  148. #endif
  149.  
  150. #ifndef INT_MIN
  151. #define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
  152. #endif
  153. #ifndef INT_MAX
  154. #define INT_MAX (~0 - INT_MIN)
  155. #endif
  156.  
  157. #ifndef TIME_T_MIN
  158. #define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
  159.             : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
  160. #endif
  161. #ifndef TIME_T_MAX
  162. #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
  163. #endif
  164.  
  165. #define TM_YEAR_BASE 1900
  166. #define EPOCH_YEAR 1970
  167.  
  168. #ifndef __isleap
  169. /* Nonzero if YEAR is a leap year (every 4 years,
  170.    except every 100th isn't, and every 400th is).  */
  171. #define    __isleap(year)    \
  172.   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  173. #endif
  174.  
  175. /* How many days come before each month (0-12).  */
  176. const unsigned short int __mon_yday[2][13] =
  177.   {
  178.     /* Normal years.  */
  179.     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  180.     /* Leap years.  */
  181.     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  182.   };
  183.  
  184. static time_t ydhms_tm_diff PARAMS ((int, int, int, int, int, const struct tm *));
  185. time_t __mktime_internal PARAMS ((struct tm *,
  186.                    struct tm *(*) (const time_t *, struct tm *),
  187.                    time_t *));
  188.  
  189.  
  190. #if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
  191. #ifdef _LIBC
  192. #define localtime_r __localtime_r
  193. #else
  194. /* Approximate localtime_r as best we can in its absence.  */
  195. #define localtime_r my_localtime_r
  196. static struct tm *localtime_r PARAMS ((const time_t *, struct tm *));
  197. static struct tm *
  198. localtime_r (t, tp)
  199.      const time_t *t;
  200.      struct tm *tp;
  201. {
  202.   struct tm *l = localtime (t);
  203.   if (! l)
  204.     return 0;
  205.   *tp = *l;
  206.   return tp;
  207. }
  208. #endif /* ! _LIBC */
  209. #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
  210.  
  211.  
  212. /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
  213.    measured in seconds, ignoring leap seconds.
  214.    YEAR uses the same numbering as TM->tm_year.
  215.    All values are in range, except possibly YEAR.
  216.    If overflow occurs, yield the low order bits of the correct answer.  */
  217. static time_t
  218. ydhms_tm_diff (year, yday, hour, min, sec, tp)
  219.      int year, yday, hour, min, sec;
  220.      const struct tm *tp;
  221. {
  222.   /* Compute intervening leap days correctly even if year is negative.
  223.      Take care to avoid int overflow.  time_t overflow is OK, since
  224.      only the low order bits of the correct time_t answer are needed.
  225.      Don't convert to time_t until after all divisions are done, since
  226.      time_t might be unsigned.  */
  227.   int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
  228.   int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
  229.   int a100 = a4 / 25 - (a4 % 25 < 0);
  230.   int b100 = b4 / 25 - (b4 % 25 < 0);
  231.   int a400 = a100 >> 2;
  232.   int b400 = b100 >> 2;
  233.   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
  234.   time_t years = year - (time_t) tp->tm_year;
  235.   time_t days = (365 * years + intervening_leap_days
  236.          + (yday - tp->tm_yday));
  237.   return (60 * (60 * (24 * days + (hour - tp->tm_hour))
  238.         + (min - tp->tm_min))
  239.       + (sec - tp->tm_sec));
  240. }
  241.  
  242.  
  243. static time_t localtime_offset;
  244.  
  245. /* Convert *TP to a time_t value.  */
  246. time_t
  247. mktime (tp)
  248.      struct tm *tp;
  249. {
  250. #ifdef _LIBC
  251.   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
  252.      time zone names contained in the external variable `tzname' shall
  253.      be set as if the tzset() function had been called.  */
  254.   __tzset ();
  255. #endif
  256.  
  257.   return __mktime_internal (tp, localtime_r, &localtime_offset);
  258. }
  259.  
  260. /* Convert *TP to a time_t value, inverting
  261.    the monotonic and mostly-unit-linear conversion function CONVERT.
  262.    Use *OFFSET to keep track of a guess at the offset of the result,
  263.    compared to what the result would be for UTC without leap seconds.
  264.    If *OFFSET's guess is correct, only one CONVERT call is needed.  */
  265. time_t
  266. __mktime_internal (tp, convert, offset)
  267.      struct tm *tp;
  268.      struct tm *(*convert) PARAMS ((const time_t *, struct tm *));
  269.      time_t *offset;
  270. {
  271.   time_t t, dt, t0;
  272.   struct tm tm;
  273.  
  274.   /* The maximum number of probes (calls to CONVERT) should be enough
  275.      to handle any combinations of time zone rule changes, solar time,
  276.      and leap seconds.  Posix.1 prohibits leap seconds, but some hosts
  277.      have them anyway.  */
  278.   int remaining_probes = 4;
  279.  
  280.   /* Time requested.  Copy it in case CONVERT modifies *TP; this can
  281.      occur if TP is localtime's returned value and CONVERT is localtime.  */
  282.   int sec = tp->tm_sec;
  283.   int min = tp->tm_min;
  284.   int hour = tp->tm_hour;
  285.   int mday = tp->tm_mday;
  286.   int mon = tp->tm_mon;
  287.   int year_requested = tp->tm_year;
  288.   int isdst = tp->tm_isdst;
  289.  
  290.   /* Ensure that mon is in range, and set year accordingly.  */
  291.   int mon_remainder = mon % 12;
  292.   int negative_mon_remainder = mon_remainder < 0;
  293.   int mon_years = mon / 12 - negative_mon_remainder;
  294.   int year = year_requested + mon_years;
  295.  
  296.   /* The other values need not be in range:
  297.      the remaining code handles minor overflows correctly,
  298.      assuming int and time_t arithmetic wraps around.
  299.      Major overflows are caught at the end.  */
  300.  
  301.   /* Calculate day of year from year, month, and day of month.
  302.      The result need not be in range.  */
  303.   int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
  304.            [mon_remainder + 12 * negative_mon_remainder])
  305.           + mday - 1);
  306.  
  307. #if LEAP_SECONDS_POSSIBLE
  308.   /* Handle out-of-range seconds specially,
  309.      since ydhms_tm_diff assumes every minute has 60 seconds.  */
  310.   int sec_requested = sec;
  311.   if (sec < 0)
  312.     sec = 0;
  313.   if (59 < sec)
  314.     sec = 59;
  315. #endif
  316.  
  317.   /* Invert CONVERT by probing.  First assume the same offset as last time.
  318.      Then repeatedly use the error to improve the guess.  */
  319.  
  320.   tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
  321.   tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
  322.   t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
  323.  
  324.   for (t = t0 + *offset;
  325.        (dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
  326.        t += dt)
  327.     if (--remaining_probes == 0)
  328.       return -1;
  329.  
  330.   /* Check whether tm.tm_isdst has the requested value, if any.  */
  331.   if (0 <= isdst && 0 <= tm.tm_isdst)
  332.     {
  333.       int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
  334.       if (dst_diff)
  335.     {
  336.       /* Move two hours in the direction indicated by the disagreement,
  337.          probe some more, and switch to a new time if found.
  338.          The largest known fallback due to daylight savings is two hours:
  339.          once, in Newfoundland, 1988-10-30 02:00 -> 00:00.  */
  340.       time_t ot = t - 2 * 60 * 60 * dst_diff;
  341.       while (--remaining_probes != 0)
  342.         {
  343.           struct tm otm;
  344.           if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
  345.                      (*convert) (&ot, &otm))))
  346.         {
  347.           t = ot;
  348.           tm = otm;
  349.           break;
  350.         }
  351.           if ((ot += dt) == t)
  352.         break;  /* Avoid a redundant probe.  */
  353.         }
  354.     }
  355.     }
  356.  
  357.   *offset = t - t0;
  358.  
  359. #if LEAP_SECONDS_POSSIBLE
  360.   if (sec_requested != tm.tm_sec)
  361.     {
  362.       /* Adjust time to reflect the tm_sec requested, not the normalized value.
  363.      Also, repair any damage from a false match due to a leap second.  */
  364.       t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
  365.       (*convert) (&t, &tm);
  366.     }
  367. #endif
  368.  
  369.   if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
  370.     {
  371.       /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
  372.      so check for major overflows.  A gross check suffices,
  373.      since if t has overflowed, it is off by a multiple of
  374.      TIME_T_MAX - TIME_T_MIN + 1.  So ignore any component of
  375.      the difference that is bounded by a small value.  */
  376.  
  377.       double dyear = (double) year_requested + mon_years - tm.tm_year;
  378.       double dday = 366 * dyear + mday;
  379.       double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
  380.  
  381.       if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
  382.     return -1;
  383.     }
  384.  
  385.   *tp = tm;
  386.   return t;
  387. }
  388.  
  389. #ifdef weak_alias
  390. weak_alias (mktime, timelocal)
  391. #endif
  392. #endif /* HAVE_MKTIME */
  393.  
  394.  
  395. #ifndef HAVE_STRPTIME
  396. /* From GNU libc 2.0, by Ulrich Drepper <drepper@gnu.ai.mit.edu>.  */
  397. /* Ulrich, thanks for helping me!  */
  398.  
  399. /* strptime - Convert a string representation of time to a time value.
  400.    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
  401.    This file is part of the GNU C Library.
  402.    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.  */
  403.  
  404. /* XXX This version of the implementation is not really complete.
  405.    Some of the fields cannot add information alone.  But if seeing
  406.    some of them in the same format (such as year, week and weekday)
  407.    this is enough information for determining the date.  */
  408.  
  409.  
  410. #if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
  411. #ifdef _LIBC
  412. #define localtime_r __localtime_r
  413. #else
  414. /* Approximate localtime_r as best we can in its absence.  */
  415. #define localtime_r my_localtime_r
  416. static struct tm *
  417. localtime_r (const time_t *t, struct tm *tp)
  418. {
  419.   struct tm *l = localtime (t);
  420.   if (! l)
  421.     return 0;
  422.   *tp = *l;
  423.   return tp;
  424. }
  425. #endif /* ! _LIBC */
  426. #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
  427.  
  428.  
  429. #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
  430. #if defined __GNUC__ && __GNUC__ >= 2
  431. # define match_string(cs1, s2) \
  432.   ({ size_t len = strlen (cs1);                              \
  433.      int result = strncasecmp ((cs1), (s2), len) == 0;                  \
  434.      if (result) (s2) += len;                              \
  435.      result; })
  436. #else
  437. /* Oh come on.  Get a reasonable compiler.  */
  438. # define match_string(cs1, s2) \
  439.   (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
  440. #endif
  441. /* We intentionally do not use isdigit() for testing because this will
  442.    lead to problems with the wide character version.  */
  443. #define get_number(from, to) \
  444.   do {                                          \
  445.     val = 0;                                      \
  446.     if (*rp < '0' || *rp > '9')                              \
  447.       return NULL;                                  \
  448.     do {                                      \
  449.       val *= 10;                                  \
  450.       val += *rp++ - '0';                              \
  451.     } while (val * 10 <= to && *rp >= '0' && *rp <= '9');              \
  452.     if (val < from || val > to)                              \
  453.       return NULL;                                  \
  454.   } while (0)
  455. #ifdef _NL_CURRENT
  456. # define get_alt_number(from, to) \
  457.   do {                                          \
  458.     if (*decided != raw)                              \
  459.       {                                          \
  460.     const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);              \
  461.     val = 0;                                  \
  462.     while (*alts != '\0')                              \
  463.       {                                      \
  464.         size_t len = strlen (alts);                          \
  465.         if (strncasecmp (alts, rp, len) == 0)                  \
  466.           break;                                  \
  467.         alts = strchr (alts, '\0') + 1;                      \
  468.         ++val;                                  \
  469.       }                                      \
  470.     if (*alts == '\0')                              \
  471.       {                                      \
  472.         if (*decided == loc && val != 0)                      \
  473.           return NULL;                              \
  474.       }                                      \
  475.     else                                      \
  476.       {                                      \
  477.         *decided = loc;                              \
  478.         break;                                  \
  479.       }                                      \
  480.       }                                          \
  481.     get_number (from, to);                              \
  482.   } while (0)
  483. #else
  484. # define get_alt_number(from, to) \
  485.   /* We don't have the alternate representation.  */                  \
  486.   get_number(from, to)
  487. #endif
  488. #define recursive(new_fmt) \
  489.   (*(new_fmt) != '\0'                                  \
  490.    && strptime_internal (rp, (new_fmt), tm, decided) != NULL)
  491.  
  492.  
  493. #ifdef _LIBC
  494. /* This is defined in locale/C-time.c in the GNU libc.  */
  495. extern const struct locale_data _nl_C_LC_TIME;
  496.  
  497. # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
  498. # define ab_weekday_name \
  499.   (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
  500. # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
  501. # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
  502. # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
  503. # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
  504. # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
  505. # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
  506. # define HERE_T_FMT_AMPM \
  507.   (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
  508. # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
  509. #else
  510. static char const weekday_name[][10] =
  511.   {
  512.     "Sunday", "Monday", "Tuesday", "Wednesday",
  513.     "Thursday", "Friday", "Saturday"
  514.   };
  515. static char const ab_weekday_name[][4] =
  516.   {
  517.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  518.   };
  519. static char const month_name[][10] =
  520.   {
  521.     "January", "February", "March", "April", "May", "June",
  522.     "July", "August", "September", "October", "November", "December"
  523.   };
  524. static char const ab_month_name[][4] =
  525.   {
  526.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  527.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  528.   };
  529. # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
  530. # define HERE_D_FMT "%m/%d/%y"
  531. # define HERE_AM_STR "AM"
  532. # define HERE_PM_STR "PM"
  533. # define HERE_T_FMT_AMPM "%I:%M:%S %p"
  534. # define HERE_T_FMT "%H:%M:%S"
  535. #endif
  536.  
  537. /* Status of lookup: do we use the locale data or the raw data?  */
  538. enum locale_status { not, loc, raw };
  539.  
  540.  
  541. static char *
  542. strptime_internal (const char *buf, const char *format, struct tm *tm,
  543.            enum locale_status *decided)
  544. {
  545.   const char *rp;
  546.   const char *fmt;
  547.   int cnt;
  548.   size_t val;
  549.   int have_I, is_pm;
  550.  
  551.   rp = buf;
  552.   fmt = format;
  553.   have_I = is_pm = 0;
  554.  
  555.   while (*fmt != '\0')
  556.     {
  557.       /* A white space in the format string matches 0 more or white
  558.      space in the input string.  */
  559.       if (isspace (*fmt))
  560.     {
  561.       while (isspace (*rp))
  562.         ++rp;
  563.       ++fmt;
  564.       continue;
  565.     }
  566.  
  567.       /* Any character but `%' must be matched by the same character
  568.      in the iput string.  */
  569.       if (*fmt != '%')
  570.     {
  571.       match_char (*fmt++, *rp++);
  572.       continue;
  573.     }
  574.  
  575.       ++fmt;
  576. #ifndef _NL_CURRENT
  577.       /* We need this for handling the `E' modifier.  */
  578.     start_over:
  579. #endif
  580.       switch (*fmt++)
  581.     {
  582.     case '%':
  583.       /* Match the `%' character itself.  */
  584.       match_char ('%', *rp++);
  585.       break;
  586.     case 'a':
  587.     case 'A':
  588.       /* Match day of week.  */
  589.       for (cnt = 0; cnt < 7; ++cnt)
  590.         {
  591. #ifdef _NL_CURRENT
  592.           if (*decided !=raw)
  593.         {
  594.           if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
  595.             {
  596.               if (*decided == not
  597.               && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
  598.                      ab_weekday_name[cnt]))
  599.             *decided = loc;
  600.               break;
  601.             }
  602.           if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
  603.             {
  604.               if (*decided == not
  605.               && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
  606.                      weekday_name[cnt]))
  607.             *decided = loc;
  608.               break;
  609.             }
  610.         }
  611. #endif
  612.           if (*decided != loc
  613.           && (match_string (ab_weekday_name[cnt], rp)
  614.               || match_string (weekday_name[cnt], rp)))
  615.         {
  616.           *decided = raw;
  617.           break;
  618.         }
  619.         }
  620.       if (cnt == 7)
  621.         /* Does not match a weekday name.  */
  622.         return NULL;
  623.       tm->tm_wday = cnt;
  624.       break;
  625.     case 'b':
  626.     case 'B':
  627.     case 'h':
  628.       /* Match month name.  */
  629.       for (cnt = 0; cnt < 12; ++cnt)
  630.         {
  631. #ifdef _NL_CURRENT
  632.           if (*decided !=raw)
  633.         {
  634.           if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
  635.             {
  636.               if (*decided == not
  637.               && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
  638.                      ab_month_name[cnt]))
  639.             *decided = loc;
  640.               break;
  641.             }
  642.           if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
  643.             {
  644.               if (*decided == not
  645.               && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
  646.                      month_name[cnt]))
  647.             *decided = loc;
  648.               break;
  649.             }
  650.         }
  651. #endif
  652.           if (match_string (ab_month_name[cnt], rp)
  653.           || match_string (month_name[cnt], rp))
  654.         {
  655.           *decided = raw;
  656.           break;
  657.         }
  658.         }
  659.       if (cnt == 12)
  660.         /* Does not match a month name.  */
  661.         return NULL;
  662.       tm->tm_mon = cnt;
  663.       break;
  664.     case 'c':
  665.       /* Match locale's date and time format.  */
  666. #ifdef _NL_CURRENT
  667.       if (*decided != raw)
  668.         {
  669.           if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
  670.         {
  671.           if (*decided == loc)
  672.             return NULL;
  673.         }
  674.           else
  675.         {
  676.           if (*decided == not &&
  677.               strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
  678.             *decided = loc;
  679.           break;
  680.         }
  681.           *decided = raw;
  682.         }
  683. #endif
  684.       if (!recursive (HERE_D_T_FMT))
  685.         return NULL;
  686.       break;
  687.     case 'C':
  688.       /* Match century number.  */
  689.       get_number (0, 99);
  690.       /* We don't need the number.  */
  691.       break;
  692.     case 'd':
  693.     case 'e':
  694.       /* Match day of month.  */
  695.       get_number (1, 31);
  696.       tm->tm_mday = val;
  697.       break;
  698.     case 'x':
  699. #ifdef _NL_CURRENT
  700.       if (*decided != raw)
  701.         {
  702.           if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
  703.         {
  704.           if (*decided == loc)
  705.             return NULL;
  706.         }
  707.           else
  708.         {
  709.           if (decided == not
  710.               && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
  711.             *decided = loc;
  712.           break;
  713.         }
  714.           *decided = raw;
  715.         }
  716. #endif
  717.       /* Fall through.  */
  718.     case 'D':
  719.       /* Match standard day format.  */
  720.       if (!recursive (HERE_D_FMT))
  721.         return NULL;
  722.       break;
  723.     case 'H':
  724.       /* Match hour in 24-hour clock.  */
  725.       get_number (0, 23);
  726.       tm->tm_hour = val;
  727.       have_I = 0;
  728.       break;
  729.     case 'I':
  730.       /* Match hour in 12-hour clock.  */
  731.       get_number (1, 12);
  732.       tm->tm_hour = val - 1;
  733.       have_I = 1;
  734.       break;
  735.     case 'j':
  736.       /* Match day number of year.  */
  737.       get_number (1, 366);
  738.       tm->tm_yday = val - 1;
  739.       break;
  740.     case 'm':
  741.       /* Match number of month.  */
  742.       get_number (1, 12);
  743.       tm->tm_mon = val - 1;
  744.       break;
  745.     case 'M':
  746.       /* Match minute.  */
  747.       get_number (0, 59);
  748.       tm->tm_min = val;
  749.       break;
  750.     case 'n':
  751.     case 't':
  752.       /* Match any white space.  */
  753.       while (isspace (*rp))
  754.         ++rp;
  755.       break;
  756.     case 'p':
  757.       /* Match locale's equivalent of AM/PM.  */
  758. #ifdef _NL_CURRENT
  759.       if (*decided != raw)
  760.         {
  761.           if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
  762.         {
  763.           if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
  764.             *decided = loc;
  765.           break;
  766.         }
  767.           if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
  768.         {
  769.           if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
  770.             *decided = loc;
  771.           is_pm = 1;
  772.           break;
  773.         }
  774.           *decided = raw;
  775.         }
  776. #endif
  777.       if (!match_string (HERE_AM_STR, rp))
  778.         if (match_string (HERE_PM_STR, rp))
  779.           is_pm = 1;
  780.         else
  781.           return NULL;
  782.       break;
  783.     case 'r':
  784. #ifdef _NL_CURRENT
  785.       if (*decided != raw)
  786.         {
  787.           if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
  788.         {
  789.           if (*decided == loc)
  790.             return NULL;
  791.         }
  792.           else
  793.         {
  794.           if (*decided == not &&
  795.               strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
  796.                   HERE_T_FMT_AMPM))
  797.             *decided = loc;
  798.           break;
  799.         }
  800.           *decided = raw;
  801.         }
  802. #endif
  803.       if (!recursive (HERE_T_FMT_AMPM))
  804.         return NULL;
  805.       break;
  806.     case 'R':
  807.       if (!recursive ("%H:%M"))
  808.         return NULL;
  809.       break;
  810.     case 's':
  811.       {
  812.         /* The number of seconds may be very high so we cannot use
  813.            the `get_number' macro.  Instead read the number
  814.            character for character and construct the result while
  815.            doing this.  */
  816.         time_t secs;
  817.         if (*rp < '0' || *rp > '9')
  818.           /* We need at least one digit.  */
  819.           return NULL;
  820.  
  821.         do
  822.           {
  823.         secs *= 10;
  824.         secs += *rp++ - '0';
  825.           }
  826.         while (*rp >= '0' && *rp <= '9');
  827.  
  828.         if (localtime_r (&secs, tm) == NULL)
  829.           /* Error in function.  */
  830.           return NULL;
  831.       }
  832.       break;
  833.     case 'S':
  834.       get_number (0, 61);
  835.       tm->tm_sec = val;
  836.       break;
  837.     case 'X':
  838. #ifdef _NL_CURRENT
  839.       if (*decided != raw)
  840.         {
  841.           if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
  842.         {
  843.           if (*decided == loc)
  844.             return NULL;
  845.         }
  846.           else
  847.         {
  848.           if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
  849.             *decided = loc;
  850.           break;
  851.         }
  852.           *decided = raw;
  853.         }
  854. #endif
  855.       /* Fall through.  */
  856.     case 'T':
  857.       if (!recursive (HERE_T_FMT))
  858.         return NULL;
  859.       break;
  860.     case 'u':
  861.       get_number (1, 7);
  862.       tm->tm_wday = val % 7;
  863.       break;
  864.     case 'g':
  865.       get_number (0, 99);
  866.       /* XXX This cannot determine any field in TM.  */
  867.       break;
  868.     case 'G':
  869.       if (*rp < '0' || *rp > '9')
  870.         return NULL;
  871.       /* XXX Ignore the number since we would need some more
  872.          information to compute a real date.  */
  873.       do
  874.         ++rp;
  875.       while (*rp >= '0' && *rp <= '9');
  876.       break;
  877.     case 'U':
  878.     case 'V':
  879.     case 'W':
  880.       get_number (0, 53);
  881.       /* XXX This cannot determine any field in TM without some
  882.          information.  */
  883.       break;
  884.     case 'w':
  885.       /* Match number of weekday.  */
  886.       get_number (0, 6);
  887.       tm->tm_wday = val;
  888.       break;
  889.     case 'y':
  890.       /* Match year within century.  */
  891.       get_number (0, 99);
  892.       tm->tm_year = val;
  893.       break;
  894.     case 'Y':
  895.       /* Match year including century number.  */
  896.       get_number (0, INT_MAX);
  897.       tm->tm_year = val - (val >= 2000 ? 2000 : 1900);
  898.       break;
  899.     case 'Z':
  900.       /* XXX How to handle this?  */
  901.       break;
  902.     case 'E':
  903. #ifdef _NL_CURRENT
  904.       switch (*fmt++)
  905.         {
  906.         case 'c':
  907.           /* Match locale's alternate date and time format.  */
  908.           if (*decided != raw)
  909.         {
  910.           const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
  911.  
  912.           if (*fmt == '\0')
  913.             fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
  914.  
  915.           if (!recursive (fmt))
  916.             {
  917.               if (*decided == loc)
  918.             return NULL;
  919.             }
  920.           else
  921.             {
  922.               if (strcmp (fmt, HERE_D_T_FMT))
  923.             *decided = loc;
  924.               break;
  925.             }
  926.           *decided = raw;
  927.         }
  928.           /* The C locale has no era information, so use the
  929.          normal representation.  */
  930.           if (!recursive (HERE_D_T_FMT))
  931.         return NULL;
  932.           break;
  933.         case 'C':
  934.         case 'y':
  935.         case 'Y':
  936.           /* Match name of base year in locale's alternate
  937.          representation.  */
  938.           /* XXX This is currently not implemented.  It should
  939.          use the value _NL_CURRENT (LC_TIME, ERA).  */
  940.           break;
  941.         case 'x':
  942.           if (*decided != raw)
  943.         {
  944.           const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
  945.  
  946.           if (*fmt == '\0')
  947.             fmt = _NL_CURRENT (LC_TIME, D_FMT);
  948.  
  949.           if (!recursive (fmt))
  950.             {
  951.               if (*decided == loc)
  952.             return NULL;
  953.             }
  954.           else
  955.             {
  956.               if (strcmp (fmt, HERE_D_FMT))
  957.             *decided = loc;
  958.               break;
  959.             }
  960.           *decided = raw;
  961.         }
  962.           if (!recursive (HERE_D_FMT))
  963.         return NULL;
  964.           break;
  965.         case 'X':
  966.           if (*decided != raw)
  967.         {
  968.           const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
  969.  
  970.           if (*fmt == '\0')
  971.             fmt = _NL_CURRENT (LC_TIME, T_FMT);
  972.  
  973.           if (!recursive (fmt))
  974.             {
  975.               if (*decided == loc)
  976.             return NULL;
  977.             }
  978.           else
  979.             {
  980.               if (strcmp (fmt, HERE_T_FMT))
  981.             *decided = loc;
  982.               break;
  983.             }
  984.           *decided = raw;
  985.         }
  986.           if (!recursive (HERE_T_FMT))
  987.         return NULL;
  988.           break;
  989.         default:
  990.           return NULL;
  991.         }
  992.       break;
  993. #else
  994.       /* We have no information about the era format.  Just use
  995.          the normal format.  */
  996.       if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
  997.           && *fmt != 'x' && *fmt != 'X')
  998.         /* This is an illegal format.  */
  999.         return NULL;
  1000.  
  1001.       goto start_over;
  1002. #endif
  1003.     case 'O':
  1004.       switch (*fmt++)
  1005.         {
  1006.         case 'd':
  1007.         case 'e':
  1008.           /* Match day of month using alternate numeric symbols.  */
  1009.           get_alt_number (1, 31);
  1010.           tm->tm_mday = val;
  1011.           break;
  1012.         case 'H':
  1013.           /* Match hour in 24-hour clock using alternate numeric
  1014.          symbols.  */
  1015.           get_alt_number (0, 23);
  1016.           tm->tm_hour = val;
  1017.           have_I = 0;
  1018.           break;
  1019.         case 'I':
  1020.           /* Match hour in 12-hour clock using alternate numeric
  1021.          symbols.  */
  1022.           get_alt_number (1, 12);
  1023.           tm->tm_hour = val - 1;
  1024.           have_I = 1;
  1025.           break;
  1026.         case 'm':
  1027.           /* Match month using alternate numeric symbols.  */
  1028.           get_alt_number (1, 12);
  1029.           tm->tm_mon = val - 1;
  1030.           break;
  1031.         case 'M':
  1032.           /* Match minutes using alternate numeric symbols.  */
  1033.           get_alt_number (0, 59);
  1034.           tm->tm_min = val;
  1035.           break;
  1036.         case 'S':
  1037.           /* Match seconds using alternate numeric symbols.  */
  1038.           get_alt_number (0, 61);
  1039.           tm->tm_sec = val;
  1040.           break;
  1041.         case 'U':
  1042.         case 'V':
  1043.         case 'W':
  1044.           get_alt_number (0, 53);
  1045.           /* XXX This cannot determine any field in TM without
  1046.          further information.  */
  1047.           break;
  1048.         case 'w':
  1049.           /* Match number of weekday using alternate numeric symbols.  */
  1050.           get_alt_number (0, 6);
  1051.           tm->tm_wday = val;
  1052.           break;
  1053.         case 'y':
  1054.           /* Match year within century using alternate numeric symbols.  */
  1055.           get_alt_number (0, 99);
  1056.           break;
  1057.         default:
  1058.           return NULL;
  1059.         }
  1060.       break;
  1061.     default:
  1062.       return NULL;
  1063.     }
  1064.     }
  1065.  
  1066.   if (have_I && is_pm)
  1067.     tm->tm_hour += 12;
  1068.  
  1069.   return (char *) rp;
  1070. }
  1071.  
  1072.  
  1073. char *
  1074. strptime (const char *buf, const char *format, struct tm *tm)
  1075. {
  1076.   enum locale_status decided;
  1077. #ifdef _NL_CURRENT
  1078.   decided = not;
  1079. #else
  1080.   decided = raw;
  1081. #endif
  1082.   return strptime_internal (buf, format, tm, &decided);
  1083. }
  1084.  
  1085. #endif /* HAVE_STRPTIME */
  1086.  
  1087.